package com.franklin.ideaplugin.mybatisrunner.action;

import cn.hutool.core.util.CharUtil;
import com.franklin.ideaplugin.mybatisrunner.constant.Constants;
import com.franklin.ideaplugin.mybatisrunner.icon.PluginIcons;
import com.franklin.ideaplugin.mybatisrunner.psi.MybatisPsiElement;
import com.franklin.ideaplugin.mybatisrunner.ui.SqlRunnerForm;
import com.franklin.ideaplugin.mybatisrunner.ui.SqlRunnerFormFactory;
import com.franklin.ideaplugin.mybatisrunner.utils.MybatisSqlUtils;
import com.franklin.ideaplugin.mybatisrunner.utils.XmlUtils;
import com.franklin.ideaplugin.mybatisrunner.xml.node.MybatisNodeHandlers;
import com.franklin.ideaplugin.mybatisrunner.xml.params.MybatisParam;
import com.intellij.ide.highlighter.XmlFileType;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.sql.SqlFileType;
import com.intellij.util.LocalTimeCounter;
import org.jetbrains.annotations.NotNull;

import java.awt.event.MouseEvent;
import java.io.StringReader;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;

/**
 * @author Ye Junhui
 * @since 2024/2/19
 */
public class ExecuteSqlAction extends AnAction {


    public ExecuteSqlAction() {
        super(PluginIcons.RUN);
    }

    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {
        PsiElement psiElement = resolveElement(e);
        if (Objects.isNull(psiElement)){
            return;
        }
        MybatisPsiElement mybatisPsiElement = MybatisPsiElement.buildMybatisElement(psiElement);
        String sqlScript = mybatisPsiElement.buildSqlScript();
        PsiFileFactory psiFileFactory = PsiFileFactory.getInstance(mybatisPsiElement.getProject());
        PsiFile psiFile = psiFileFactory.createFileFromText(
                Constants.NAME,
                XmlFileType.INSTANCE,
                sqlScript,
                LocalTimeCounter.currentTime(),
                true,
                false
        );
        XmlFile xmlFile = (XmlFile) psiFile;

        XmlTag xmlTag = xmlFile.getRootTag();
        mybatisPsiElement.setSqlXmlTag(xmlTag);

        SqlRunnerFormFactory.getInstance(psiElement.getProject())
                .showSqlRunnerForm(mybatisPsiElement);
    }

    private PsiElement resolveElement(AnActionEvent anActionEvent){
        PsiFile psiFile = anActionEvent.getData(CommonDataKeys.PSI_FILE);
        Editor editor = anActionEvent.getData(CommonDataKeys.EDITOR);
        if (Objects.isNull(psiFile) || Objects.isNull(editor)) {
            return null;
        }

        //行数
        MouseEvent mouseEvent = (MouseEvent) anActionEvent.getInputEvent();
        int line = EditorUtil.yPositionToLogicalLine(editor, mouseEvent.getPoint());

        int offset = findOffset(line + 1, psiFile.getText());
        if (offset < 0) {
            return null;
        }
        PsiElement psiElement = psiFile.findElementAt(offset);
        if (psiFile instanceof PsiJavaFile){
            return PsiTreeUtil.getParentOfType(psiElement, PsiAnnotation.class);
        }
        return PsiTreeUtil.getParentOfType(psiElement,XmlTag.class);
    }

    /**
     * 寻找目标行索引
     *
     * @param targetLine
     * @param text
     * @return
     */
    private int findOffset(int targetLine, String text) {
        int lineCount = 0;
        for (int i = 0; i < text.length(); i++) {
            char c = text.charAt(i);
            if (c == '\n') {
                lineCount++;
            }
            if (lineCount == targetLine) {
                //往前找不为空的字符
                for (int j = i; j > 0; j--) {
                    char pre = text.charAt(j);
                    if (!CharUtil.isBlankChar(pre)) {
                        return j;
                    }
                }
            }
        }
        return -1;
    }
}
